package org.njo.webapp.templates.servlet;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.njo.webapp.templates.config.ConfigLoadHelper;
import org.njo.webapp.templates.config.PatternConfig;
import org.njo.webapp.templates.servlet.wrapper.StringResponseWrapper;

/**
 * 生成器控制Servlet.
 * 
 * 1,初始化时读取配置文件.
 * 
 * 2,接受到请求时,根据请求生成目标.
 *   2.1
 * 
 * 
 * @author yu.peng
 */
public class TemplateGeneratorServlet extends HttpServlet {
    
    /**
     * Servlet初始化.
     * 
     * 
     * 1,加载配置信息.注意:这个步骤只在第一次运行时执行. 
     */
    public void init() throws ServletException {
        // super.init();
        ServletContext context = this.getServletContext();
        // 读取配置信息到ServletContext中.配置文件需要在第一次请求时，加载到ServletContext中
        ConfigLoadHelper helper = ConfigLoadHelper.getInstance();
        if (!helper.isLoaded(context)) {
            String paths = getServletConfig().getInitParameter("config");
            helper.loadConfig(context, paths);
        }
    }

    /**
     * 生成器控制Action.
     * 
     * 所有的模版做生成操作时,都需要提交到这个Action.
     * 这个Action会按照以下的步骤处理.
     * 1,取得请求路径,并根据请求路径取得(模版集合)配置信息.
     *   并以'pconfig'为key,保存到request属性中.
     *   这个步骤中有一个分支,就是如果没有正确找到(匹配)
     *   到合适的模版配置信息,需要返回404错误,告知用户没有找到模版.
     *   
     * 2,计算取得输出路径.并以'ddpath'为key,保存到request属性中.
     *   注意:这个路径将作为生成结果的根目录.
     *   
     * 3,备份请求参数.
     *   以'reparam'为key,将请求参数保存成String形式.
     *   以'rparamvalues'为key,将请求参数保存成String[](数组)形式.
     *   
     * 4,TODO,转发或include,'controller.jsp',生成结果. 
     *        memo:如果使用include时需要,包装response.并需要保存生成的文件列表.
     * 
     * 5,压缩生成结果.将压缩后的文件名,以''为key,保存在request属性中.
     * 
     * 6,转发到生成成功画面.并在画面上输出生成的文件列表,以及下载连接. 
     * 
     * 
     * 注意:本应该将一些控制代码写在这个Action中,而非controller.jsp中,
     *     是由于在模版的参数中需要使用一些参数,在jsp中可以使用el来达到这个目的.
     *     比如:在配置输出文件时,可以这样配置dest='/src/${package}/${var1}Form.java'
     *         通过el转换求值就可以得到动态的报名和文件名.
     *     在Action中不能使用el,在controller.jsp的控制代码是必须的,
     *     不能转移到Action(java)程序中.因为在那里得不到pageContext.
     *     
     * @param request
     * @param response
     */
    protected void service(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        ServletContext context = this.getServletContext();

        // 根据请求路径,取得该路径对应的配置信息.分析path,取得正确模版集合(pattern),并取得配置信息
        String path = processPath(request);
        System.out.println(path);
        
        PatternConfig patternConfig = null;
        boolean finded = false;
        if (!finded) {
            return ;
        }
        request.setAttribute("pconfig", patternConfig);

        // 设定输出路径.输出输出目录,TODO:取得系统临时目录,在临时目录下根据时间戳,创建目录作为模版的输出目录
        request.setAttribute("ddpath", "c:/temp/");

        // 请求参数的备份 请求参数数组的备份
        Enumeration enu = request.getParameterNames();
        Map reparam = new HashMap();
        Map rparamvalues = new HashMap();
        request.setAttribute("reparam", reparam);
        request.setAttribute("rparamvalues", rparamvalues);
        while (enu.hasMoreElements()) {
            String paramName = (String)enu.nextElement();
            String paramValue = request.getParameter(paramName);
            String[] paramValues = request.getParameterValues(paramName);
            reparam.put(paramName, paramValue);
            rparamvalues.put(paramName, paramValues);
        }

        // 用于保存生成的文件列表
        request.setAttribute("resultFileList", new ArrayList());
        // 
        RequestDispatcher controllerRequestDispatcher = context.getRequestDispatcher("/templates/controller1.jsp");
        StringResponseWrapper responseWapper = new StringResponseWrapper(response, response.getCharacterEncoding());
        controllerRequestDispatcher.include(request, responseWapper);
        responseWapper.flush();
        responseWapper.close();
        String outputString = responseWapper.toString(); 
        
        // String zipFile = dirtoZip(ddpath, "xxxx.zip");
        // request.setAttribute("download_uri", zipFile);
        
        RequestDispatcher requestDispatcher = context.getRequestDispatcher("/display.tiles");
        requestDispatcher.forward(request, response);
        // return new ActionForword("/display.tiles", false);
    }

    private static String processPath(HttpServletRequest request) {
        
        String path = null;
        // For prefix matching, match on the path info (if any)
        path = (String) request.getAttribute("javax.servlet.include.path_info");
        if (path == null) {
            path = request.getPathInfo();
        }
        if ((path != null) && (path.length() > 0)) {
            return (path);
        }

        // For extension matching, strip the module prefix and extension
        path = (String) request.getAttribute("javax.servlet.include.servlet_path");
        if (path == null) {
            path = request.getServletPath();
        }

        int slash = path.lastIndexOf("/");
        int period = path.lastIndexOf(".");
        if ((period >= 0) && (period > slash)) {
            //path = path.substring(0, period);
            path = path.substring(slash+1, period);
        }
        return (path);
    }   
    
    
}